#include "trans.hpp"
#include "parser.hpp"
#include "error.hpp"
#include <string.h>
#include <stdio.h>

extern YYSTYPE yylval;
//extern char *yytext;

// HomoLists
bool HomoList::_codeready = false;
Type* HomoList::_type = NULL;
string HomoList::_code = "";
vector<string> HomoList::_elements;

string HomoList::code(string var) {
    if (_codeready)
        return _code;
    int offset = 0;
    Properties *variable = SymbolTable::checkvar(var);
    while (!_elements.empty()) {
        _code += variable->type->cderef(variable->value, offset++) + " = "
                + _elements.back() + ";\n";
        _elements.pop_back();
    }
    _codeready = true;
    return _code;
}

Type* HomoList::type() {
    return new Array(_type, _elements.size());
}

void HomoList::addvar(Properties& var) {
    Type* otype = _type;
    Type* vtype = var.type;
    if (!_type)
        _type = vtype;
    else if (_type->numeric())
        _type = NumericType::stronger(_type, vtype);
    else if (!_type->equals(vtype))
        _type = NULL;
    if (_type == NULL)
        Error::inctypeslist(otype, var);
    else {
        _code += var.code;
        _elements.push_back(var.value);
    }
}

void HomoList::reset() {
    _type = NULL;
    _code = "";
    _codeready = false;
    _elements.clear();
}

int HomoList::length() {
    return _elements.size();
}

// Labels static member functions.
int Labels::_iflabels = 0;

int Labels::_forlabels = 0;

int Labels::_looplabels = 0;

int Labels::iflabels() {
    return _iflabels;
}

int Labels::newiflabel() {
    return _iflabels++;
}

string Labels::then(int index) {
    char label[16];
    sprintf(label, "label_then_%03d", index);
    return string(label);
}

string Labels::endif(int index) {
    char label[17];
    sprintf(label, "label_endif_%03d", index);
    return string(label);
}

int Labels::forlabels() {
    return _forlabels;
}

int Labels::newforlabel() {
    return _forlabels++;
}

string Labels::fortest(int index) {
    char label[16];
    sprintf(label, "label_fortest_%03d", index);
    return string(label);
}

string Labels::forexit(int index) {
    char label[16];
    sprintf(label, "label_forexit_%03d", index);
    return string(label);
}

int Labels::looplabels() {
    return _looplabels;
}

int Labels::newlooplabel() {
    return _looplabels++;
}

string Labels::looptest(int index) {
    char label[16];
    sprintf(label, "label_looptest_%03d", index);
    return string(label);
}

string Labels::loopbody(int index) {
    char label[16];
    sprintf(label, "label_loopbody_%03d", index);
    return string(label);
}

string Labels::loopexit(int index) {
    char label[20];
    sprintf(label, "label_loopexit_%03d", index);
    return string(label);
}

string Labels::functionexit(int index) {
    char label[32];
    sprintf(label, "label_functionexit_%03d", index);
    return string(label);
}

void traceToken(const char* token, Type* type) {
    if (string(token) == "true")
        yylval.value = "1";
    else if (string(token) == "false")
        yylval.value = "0";
    yylval.value = token;
    yylval.type = type;
    yylval.constant = (type != NULL);
    numCol += strlen(token);
    ultimoToken = token;
    ultimaLinha += ultimoToken;
}
